package lock;

/**
 * 案例：死锁测试，死锁的四个条件
 */
public class DeadLockTest {

    //1.互斥条件：一个资源任意一个时刻只由一个线程占用，具有排它性。ReentrantLock是独占锁，满足
    public static ReentrantLock lock1 = new ReentrantLock();
    public static ReentrantLock lock2 = new ReentrantLock();

    public static void main(String[] args) {
        new Thread(() -> {
            try {
                lock1.lock();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //2.请求与保持条件：一个线程因请求资源而阻塞时，对已获得的资源保持不放。
                //在运行1秒后，线程2已经拿到了lock2的锁，因此线程1阻塞在这里，但是又不释放lock1，满足
                lock2.lock();
                System.out.println("线程1拿到了两个锁");
            } finally {
                //3.不剥夺条件: 线程已获得的资源在未使用完之前不能被其他线程强行剥夺，只有自己使用完毕后才释放资源。
                lock1.unlock();
                lock2.unlock();
            }
        }).start();

        new Thread(() -> {
            try {
                lock2.lock();
                //4.循环等待条件: 若干线程之间形成一种头尾相接的循环等待资源关系。
                //线程2也在阻塞等待获取线程1持有的lock1，互相持有对方阻塞等待的资源，循环等待形成了死锁
                lock1.lock();
                System.out.println("线程2拿到了两个锁");
            } finally {
                lock1.unlock();
                lock2.unlock();
            }
        }).start();
    }
}
